package smartgrid.agents.prosumer;

import java.util.List;
import java.util.Map;
import smartgrid.modules.normative.sanction.SanctionAbstract;
import smartgrid.modules.trade.Contract;
import smartgrid.modules.trade.Demand;
import smartgrid.modules.trade.Offer;

public interface IProsumerAgent {
	
	/**
	 * Get prosumer identification
	 * 
	 * @param none
	 * @return Prosumer identification
	 */
	public int getId();
	
	
	/**
	 * Set the agent neighbors
	 * 
	 * @param neighbors
	 *          Map of Prosumer and list of its neighbors
	 * @return none
	 */
	public void setNeighbors(Map<Integer, List<IProsumerAgent>> neighbors);
	
	
	/**
	 * Set distances among all Prosumers
	 * 
	 * @param distance
	 *          Distance among all Prosumers
	 * @return none
	 */
	public void setDistance(Map<Integer, Map<Integer, Double>> distances);
	
	
	/**
	 * Set the list of all Prosumers in the system
	 * 
	 * @param prosumers
	 *          List of prosumers
	 * @return none
	 */
	public void setProsumers(Map<Integer, IProsumerAgent> prosumers);
	
	
	/**
	 * Initialize the simulation
	 * 
	 * @param none
	 * @return none
	 */
	public void initSim();
	
	
	/**
	 * Initialize the simulation timestep
	 * 
	 * @param timestep
	 *          Number of the simulation timestep
	 * @return none
	 */
	public void initTimestep(int timestep);
	
	
	/**
	 * Estimate the amount of energy that will be consumed and generated in the
	 * next period
	 * 
	 * @param none
	 * @return none
	 */
	public void estimationConGen();
	
	
	/**
	 * Get the forecasted consumption
	 * 
	 * @return Forecasted consumption
	 */
	public double getConsumeEstimation();
	
	
	/**
	 * Get the forecasted generation
	 * 
	 * @return Forecasted generation
	 */
	public double getGenerateEstimation();
	
	
	/**
	 * Verify whether the prosumer has energy in excess to offer
	 * 
	 * @param none
	 * @return True if it has energy in excess, False otherwise
	 */
	public boolean hasExcessEnergyEstimation();
	
	
	/**
	 * Get energy offer
	 * 
	 * @param none
	 * @return Energy offer
	 */
	public Offer getOffer();
	
	
	/**
	 * Get energy demand
	 * 
	 * @param offers
	 *          All available offers
	 * @return demand Prosumer demand
	 */
	public Demand getDemand(Map<Integer, Offer> offers);
	
	
	/**
	 * Get the prosumer's contract for the period
	 * 
	 * @param none
	 * @return Contract committed
	 */
	public Contract getContract();
	
	
	/**
	 * Set the prosumer's contract for the period
	 * 
	 * @param contract
	 *          Contract committed
	 * @return none
	 */
	public void setContract(Contract contract);
	
	
	/**
	 * Calculate the real amount of energy that was consumed and generated
	 * 
	 * @param none
	 * @return none
	 */
	public void realConGen();
	
	
	/**
	 * Calculate the real consumption
	 * 
	 * @param none
	 * @return Real consumption
	 */
	public double getConsumeReal();
	
	
	/**
	 * Calculate the real generation
	 * 
	 * @param none
	 * @return Real generation
	 */
	public double getGenerateReal();
	
	
	/**
	 * Verify whether the prosumer has produced energy in excess
	 * 
	 * @param none
	 * @return True if it has energy in excess, False otherwise
	 */
	public boolean hasExcessEnergyReal();
	
	
	/**
	 * Update the contract information with the supplied energy
	 * 
	 * @param none
	 * @return none
	 */
	public void updateContract();
	
	
	/**
	 * Update the total price of the contract
	 * 
	 * @param none
	 * @return none
	 */
	public void updateWealth();
	
	
	/**
	 * Balance of consumed + received and generated + sold energy
	 * 
	 * @param none
	 * @return Energy balance
	 */
	public double energyBalance();
	
	
	/**
	 * Purchase or sell energy to the provider
	 * 
	 * @param buy
	 *          True if buy energy, False if sell
	 * @param qtyEnergy
	 *          Quantity of bought or sold energy
	 * @param totalPrice
	 *          Total price of the bought or sold energy
	 * @return none
	 */
	public void providerTrading(boolean buy, double qtyEnergy, double totalPrice);
	
	
	/**
	 * Evaluates the contract and set whether it was fulfilled or violated
	 * 
	 * @param none
	 * @return none
	 */
	public void evaluateContract();
	
	
	/**
	 * Decide the sanction to apply, if any
	 * 
	 * @param none
	 * @return Set of sanctions
	 */
	public List<SanctionAbstract> decideSanction();
	
	
	/**
	 * Apply sanction
	 * 
	 * @param sanction
	 *          Sanction to apply
	 * @return none
	 */
	public void handleSanction(SanctionAbstract sanction);
	
	
	/**
	 * Perform all the end step adjustments
	 * 
	 * @param sanctionsSender
	 *          All sanctions applied ordered by sender
	 * @param sanctionsReceiver
	 *          All sanctions applied ordered by receiver
	 * @return none
	 */
	public void updateStrategy(
			Map<Integer, List<SanctionAbstract>> sanctionsSender,
			Map<Integer, List<SanctionAbstract>> sanctionsReceiver);
	
	
	/**
	 * Get a Prosumer's output record
	 * 
	 * @param none
	 * @return Prosumer output record
	 */
	public void generateOutput();
}